package com.learn.juc.readwrite;

import com.learn.juc.cache.MyCache;
import com.learn.juc.cache.MyCacheSuper;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * ClassName:ReadWriteLockDemo
 * Package:com.learn.juc.readwrite
 * Description:
 *
 * @Author:@郭先森
 * @Create:2025/7/28 - 17:12
 * @Version:v1.0
 */
public class ReadWriteLockDemo {
    public static void main(String[] args) throws InterruptedException {
        MyCache myCache = new MyCache();
        //创建线程放数据
        for (int i = 0; i < 5; i++) {
            final int num = i;
            new Thread(()->{
                try {
                    myCache.put(num+"",num+"");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            },String.valueOf(i)).start();
        }
        //创建线程读取数据
        for (int i = 0; i < 5; i++) {
            final int num = i;
            new Thread(()->{
                try {
                    myCache.get(num+"");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            },String.valueOf(i)).start();
        }
        //以上例子顺序是乱的，还没写完就开始读了，而且写锁也不是独占锁

        //以下例子，写锁是独占锁，读写互斥，读读共享，写写互斥
        TimeUnit.SECONDS.sleep(5);
        System.out.println("***************************");
        MyCacheSuper myCacheSuper = new MyCacheSuper();
        for (int i = 0; i < 5; i++) {
            final int num = i;
            new Thread(()->{
                try {
                    myCacheSuper.put(num+"",num+"");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            },String.valueOf(i)).start();
        }
        for (int i = 0; i < 5; i++) {
            final int num = i;
            new Thread(()->{
                try {
                    myCacheSuper.get(num+"");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            },String.valueOf(i)).start();
        }
        TimeUnit.SECONDS.sleep(100);
        System.out.println("*******************");

        //读写锁也是有缺陷的，可能会造成锁饥饿，一直读，没有写的操作
        //锁降级：将写入锁降级为读锁
        //获取写锁----》获取读锁----》释放写锁---》释放读锁
        //这样当写入的时候，别的线程也可以读了
        //读写锁的例子
        ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();//创建一个可重入锁的对象
        ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();//读锁
        ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();//写锁
        writeLock.lock();
        System.out.println("开始写锁");
        readLock.lock();
        System.out.println("开始读锁");
        writeLock.unlock();
        System.out.println("释放写锁");
        readLock.unlock();
        System.out.println("释放读锁");
    }
}
